package middleware

import (
	"fmt"
	"github.com/go-kratos/kratos/v2/log"
	"net/http"
	"strconv"
	"strings"

	stdhttp "net/http"

	"github.com/go-kratos/kratos/v2/errors"
	khttp "github.com/go-kratos/kratos/v2/transport/http"
)

type responseErr struct {
	Success bool   `json:"success"`
	Error   string `json:"error"`
	ErrCode string `json:"errCode"`
}

const (
	baseContentType = "application"
)

// ContentType returns the content-type with base prefix.
func ContentType(subtype string) string {
	return strings.Join([]string{baseContentType, subtype}, "/")
}

func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {
	// 拿到error并转换成kratos Error实体
	se := errors.FromError(err)
	// 通过Request Header的Accept中提取出对应的编码器
	codec, _ := khttp.CodecForRequest(r, "Accept")
	newRes := &responseErr{Success: false}
	newRes.ErrCode = strconv.Itoa(int(se.Code))
	newRes.Error = se.Message
	newBody, err := codec.Marshal(newRes)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	w.Header().Set("Content-Type", ContentType(codec.Name()))
	// 设置HTTP Status Code
	w.WriteHeader(200) // int(se.Code)
	w.Write(newBody)
}

func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error {
	// 通过Request Header的Accept中提取出对应的编码器
	// 如果找不到则忽略报错，并使用默认json编码器
	codec, _ := khttp.CodecForRequest(r, "Accept")
	data, err := codec.Marshal(v)
	if err != nil {
		return err
	}
	// 在Response Header中写入编码器的scheme
	w.Header().Set("Content-Type", ContentType(codec.Name()))
	w.WriteHeader(200)
	w.Write(data)
	return nil
}

// NotFoundOrMethodNotAllowedHandler 路由未匹配或方法未允许 404 405
var NotFoundOrMethodNotAllowedHandler = func(httReturnCode int, logger log.Logger) stdhttp.HandlerFunc {
	return stdhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		logger.Log(log.LevelWarn, "NotFoundOrMethodNotAllowedHandler", "Request_Url", r.RequestURI)
		//if r.Method == "OPTIONS" {
		//	origin := r.Header.Get("Origin")
		//	w.Header().Set("Access-Control-Allow-Origin", origin)
		//	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
		//	w.Header().Set("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		//	w.Header().Set("Access-Control-Allow-Credentials", "true")
		//	w.Header().Set("Access-Control-Max-Age", "172800")
		//	w.WriteHeader(204)
		//	return
		//} else {
		httReturnCodeStr := fmt.Sprintf("%d", httReturnCode)
		msg := "NotFound"
		if httReturnCode == 405 {
			msg = "Method Not Allowed"
		}
		// 通过Request Header的Accept中提取出对应的编码器
		codec, _ := khttp.CodecForRequest(r, "Accept")
		newRes := &responseErr{Success: false, ErrCode: httReturnCodeStr, Error: msg}
		newBody, err := codec.Marshal(newRes)
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", ContentType(codec.Name()))
		// 设置HTTP Status Code
		w.WriteHeader(httReturnCode) // int(se.Code)
		w.Write(newBody)
		//}
	})
}

type Result[T any] struct {
	Success bool   `json:"success,omitempty"`
	Error   string `json:"error,omitempty"`
	ErrCode string `json:"errCode,omitempty"`
	Data    T      `json:"data,omitempty"`
}

//func DefaultResponseEncoder2(w http.ResponseWriter, r *http.Request, v interface{}) error {
//	// 通过Request Header的Accept中提取出对应的编码器
//	// 如果找不到则忽略报错，并使用默认json编码器
//	codec, _ := khttp.CodecForRequest(r, "Accept")
//
//	marshalOptions := protojson.MarshalOptions{
//		EmitUnpopulated: true,
//		UseProtoNames:   true,
//	}
//
//	// 将 protobuf 消息序列化为 byte
//	switch m := v.(type) {
//	case *v1.BaseResult:
//		// cc := m.GetData().MessageName()
//		// allName, _ := marshalOptions.Resolver.FindExtensionByName(cc)
//		// log.Println(allName)
//		result := &Result[*v1.AccountPo]{Success: m.Success, Error: m.Error, ErrCode: m.ErrCode, Data: &v1.AccountPo{}}
//		err := m.Data.UnmarshalTo(result.Data)
//		data, err := codec.Marshal(result)
//		if err != nil {
//			return err
//		}
//		// 在Response Header中写入编码器的scheme
//		w.Header().Set("Content-Type", ContentType(codec.Name()))
//		w.Write(data)
//		return nil
//	case proto.Message:
//		cc := m.ProtoReflect().Descriptor().FullName() // base.v1.BaseResult
//		log.Println(cc)
//		data, _ := marshalOptions.Marshal(m)
//		w.Header().Set("Content-Type", ContentType(codec.Name()))
//		w.Write(data)
//		return nil
//	default:
//	}
//
//	data, err := codec.Marshal(v)
//	if err != nil {
//		return err
//	}
//	// 在Response Header中写入编码器的scheme
//	w.Header().Set("Content-Type", ContentType(codec.Name()))
//	w.Write(data)
//	return nil
//}

//func DefaultResponseEncoder3(w http.ResponseWriter, r *http.Request, v interface{}) error {
//	// 通过Request Header的Accept中提取出对应的编码器
//	// 如果找不到则忽略报错，并使用默认json编码器
//	// 将Go结构体编码为JSON
//	// 将protobuf消息转换为JSON
//	jsonData, err := protojson.MarshalOptions{
//		EmitUnpopulated: true, // 如果需要，可以设置为true以包含未设置的字段
//		UseProtoNames:   true, // 如果你的字段使用proto的名字，可以设置为true
//	}.Marshal(v.(proto.Message))
//	if err != nil {
//		return err
//	}
//	log.Println(jsonData)
//	w.Header().Set("Content-Type", ContentType("json"))
//	w.Write(jsonData)
//	return nil
//}
